﻿using UnityEngine;
using System.Collections;
using XInputDotNetPure; // Required in C#

public class PlayerMovement : MonoBehaviour {

	// x-box-ohjain
	bool playerIndexSet = false;
	PlayerIndex playerIndex;
	GamePadState state;
	GamePadState prevState;
	
	
	public GameObject shoot_target;
	
	public PlayerHealth hp_system;
	
	// omat napit
	public bool left_btn = false;
	public bool right_btn = false;
	public bool jump_btn = false;
	public bool shoot_btn = false;
	public bool fly_btn = false;
	public float fly_btn_t = 0f;
	
	public bool zoom_btn = false;
	
	public float walking_force = 40f;
	public float jumping_force = 22f;
	public float flying_force = 1f;
	public int can_jump = 2;
	public bool is_wallsliding = false;
	private bool need_keyup = false;
	private Vector3 jump_dir = Vector3.up;
	
	public bool grounded = false;
	
	public float friction = 0f;
	public float air_time = 0f;
	
	public bool disable_movement = false;
	
	private Vector3 lastpos;
	private Vector3 poschanged;
	
	private ParticleSystem thruster;
	

	// Use this for initialization
	void Start () {
		friction = rigidbody2D.drag;
		
		thruster = gameObject.GetComponentInChildren<ParticleSystem>();
	}
	
	void UpdInput()
	{
		
		// Find a PlayerIndex, for a single player game
		// Will find the first controller that is connected ans use it
		if (!playerIndexSet || !prevState.IsConnected)
		{
			for (int i = 0; i < 4; ++i)
			{
				PlayerIndex testPlayerIndex = (PlayerIndex)i;
				GamePadState testState = GamePad.GetState(testPlayerIndex);
				if (testState.IsConnected)
				{
					Debug.Log(string.Format("GamePad found {0}", testPlayerIndex));
					playerIndex = testPlayerIndex;
					playerIndexSet = true;
				}
			}
		}
		
		prevState = state;
		state = GamePad.GetState(playerIndex);
		
		
		
		
		left_btn = false;
		right_btn = false;
		jump_btn = false;
		shoot_btn = false;
		fly_btn = false;
		zoom_btn = false;
		
		//print (Input.GetAxis("Horizontal"));
		
		// zoomi
		if (state.Buttons.LeftShoulder == ButtonState.Pressed || state.Buttons.RightShoulder == ButtonState.Pressed)
			zoom_btn = true;
		if (Input.GetKey(KeyCode.Z))
			zoom_btn = true;
		
		// Restart
		if (state.Buttons.Start == ButtonState.Pressed)
			Application.LoadLevel(Application.loadedLevel);
		
		// walking
		if (Input.GetKey(KeyCode.A)/*) || state.DPad.Left == ButtonState.Pressed*/ || state.ThumbSticks.Left.X<-0.1f)
			left_btn = true;
		if (Input.GetKey(KeyCode.D)/* || state.DPad.Right == ButtonState.Pressed*/ || state.ThumbSticks.Left.X>0.1f)
			right_btn = true;
			
		// jumping
		if (Input.GetKey(KeyCode.W))
			jump_btn = true;
		if (state.Buttons.A == ButtonState.Pressed)
			jump_btn = true;
		if (state.Triggers.Left > 0.1f)
			jump_btn = true;
		//if (state.Buttons.LeftShoulder == ButtonState.Pressed || state.Buttons.RightShoulder == ButtonState.Pressed)
		//	jump_btn = true;
		
		// shoot
		if (state.Triggers.Right > 0.1f)// || state.Triggers.Left > 0.1f)
			shoot_btn = true;
		if(Input.GetMouseButton(0))
			shoot_btn = true;
		//if (state.Buttons.X == ButtonState.Pressed)
		//	shoot_btn = true;
			
		// flying
		if(jump_btn)
			fly_btn_t+=Time.deltaTime;
		else
			fly_btn_t = 0f;
		if(fly_btn_t >= 0.5f)
			fly_btn = true;
		if(jump_btn && (need_keyup==false || fly_btn==true))
		{
			if(can_jump <= 0)
				fly_btn = true;
		}
			
		//if (state.Buttons.Y == ButtonState.Pressed)
		//	fly_btn = true;
		//if (state.Triggers.Left > 0.1f)
		//	fly_btn = true;
		//if (Input.GetKey(KeyCode.S))
		//	fly_btn = true;
		
		
		// d-pad aiming
		/*
		if(state.DPad.Left == ButtonState.Pressed ||
		   state.DPad.Right == ButtonState.Pressed ||
		   state.DPad.Up == ButtonState.Pressed ||
		   state.DPad.Down == ButtonState.Pressed)
		{
			Vector3 p = new Vector3(state.DPad.Left-state.DPad.Right,
			                        state.DPad.Down-state.DPad.Up,
			                        0f);
			p.Normalize();
			p *= 10f;
			p += transform.position;
			shoot_target.transform.position = p;
			
			shoot_target.transform.GetChild(0).renderer.enabled = false;
		}
		// left stick aiming
		if(Mathf.Abs(state.ThumbSticks.Left.X) > 0.1f || Mathf.Abs(state.ThumbSticks.Left.Y) > 0.1f)
		{
			Vector3 p = new Vector3(state.ThumbSticks.Left.X,
			                        state.ThumbSticks.Left.Y,
			                        0f);
			p.Normalize();
			p *= 10f;
			p += transform.position;
			shoot_target.transform.position = p;
			
			shoot_target.transform.GetChild(0).renderer.enabled = false;
		}
		*/
		// right stick aiming
		if(Mathf.Abs(state.ThumbSticks.Right.X) > 0.1f || Mathf.Abs(state.ThumbSticks.Right.Y) > 0.1f)
		{
			Vector3 p = new Vector3(state.ThumbSticks.Right.X,
			                        state.ThumbSticks.Right.Y,
			                        0f);
			p.Normalize();
			p *= 10f;
			p += transform.position;
			shoot_target.transform.position = p;
			
			shoot_target.transform.GetChild(0).renderer.enabled = false;
		}
		else if(shoot_target.transform.GetChild(0).renderer.enabled == false)
		{
			poschanged = transform.position - lastpos;
			lastpos=transform.position;
			shoot_target.transform.position += poschanged;
		}
	}
	
	// Update is called once per frame
	void FixedUpdate () {
	
		// höhöhööö
		//can_jump = 2;
		
		
		if(disable_movement)
			return;
	
		UpdInput();
		
		if(IsStillGrounded())
		{
			rigidbody2D.drag = friction;
			air_time = 0f;
			jump_dir = Vector3.up;
			grounded = true;
		}
		else
		{
			rigidbody2D.drag = friction/3;
			air_time += Time.deltaTime;
			grounded = false;
		}
		
		if(grounded)
			DoWalking();
		else
			DoFalling();
			
		DoJumping();
		DoFlying();
	
	}
	
	
	bool IsWallSliding()
	{
		Vector3 extents = transform.collider2D.bounds.size;
		Vector3 ray_origin = transform.position;// - new Vector3(extents.x,0f,0f);
		
		Vector3 dir = Vector3.zero;
		
		if(right_btn)
			dir.x=1;
		else if(left_btn)
			dir.x=-1;
		else
			return false;
		
		int layer =	gameObject.layer;
		gameObject.layer = LayerMask.NameToLayer("Ignore Raycast");
		
		RaycastHit2D hit = Physics2D.Raycast(ray_origin,dir,1f);
		
		gameObject.layer=layer;
		
		Debug.DrawLine(ray_origin,ray_origin+dir);
		
		
		if(hit.point.y != 0f && hit.collider.gameObject !=null)
			return true;
		
		return false;
	}
	bool IsStillGrounded()
	{
		Vector3 extents = transform.collider2D.bounds.size;
		Vector3 plr_bottom = new Vector3(0,extents.y,0f);
		Vector3 ray_origin = transform.position - plr_bottom;
		
		if(Random.Range (0,100)<66)
		{
			if(Random.Range (0,100)<50)
				ray_origin.x+=extents.x/2;
			else
				ray_origin.x-=extents.x/2;
			
		}
		
		RaycastHit2D ground = Physics2D.Raycast(ray_origin,-Vector2.up,0.01f);
		if(ground.point.y != 0f)
			return true;
		
		return false;
	}
	void DoFlying()
	{
		if(fly_btn && Random.Range(0,PlayerHealth.max_charge) < PlayerHealth.charge*4)
		{
			rigidbody2D.velocity = new Vector2(rigidbody2D.velocity.x,rigidbody2D.velocity.y+flying_force);
			
			can_jump = 0;
			
			
			hp_system.ReduceCharge(10f*Time.deltaTime);
			
			if(thruster.isPlaying == false)
				thruster.Play();
		}
		else if(thruster.isPlaying == true)
			thruster.Stop();
	}
	void DoJumping()
	{
		
		if(jump_btn && need_keyup==false)
		{
			if(can_jump > 0)
			{
				jump_dir.y=1f;
				jump_dir.Normalize();
				
				rigidbody2D.velocity = new Vector3(rigidbody2D.velocity.x,3f,0f)+jump_dir*jumping_force;
				rigidbody2D.velocity.Normalize();
				rigidbody2D.velocity *= jumping_force/30;
				
				air_time = 0f;
				
				need_keyup = true;
				can_jump -= 1;
			}
				
			jump_dir = Vector3.up;
			
		}
		if(jump_btn==false)
			need_keyup = false;
	}
	void DoWalking()
	{
		if(left_btn)
			rigidbody2D.AddForce(new Vector2(-walking_force,0f));
		if(right_btn)
			rigidbody2D.AddForce(new Vector2(walking_force,0f));
	}
	void DoFalling()
	{
		if(left_btn)
			rigidbody2D.AddForce(new Vector2(-walking_force/3,0f));
		if(right_btn)
			rigidbody2D.AddForce(new Vector2(walking_force/3,0f));
			
		// wall slide
		is_wallsliding = false;
		if(fly_btn==false)
		{
			if(jump_dir.y>=0.0f && jump_dir.y<=0.9f)// && can_jump == 2)
			{
				if(IsWallSliding())
				{
					if((left_btn && jump_dir.x>=0.1f) || (right_btn && jump_dir.x<=-0.1f))
					{
						
						rigidbody2D.velocity = new Vector2(0f,-1f);
						is_wallsliding = true;
						
					}
					else
						jump_dir = Vector3.up;
				}
				else
				{
					jump_dir = Vector3.up;
				}
			}
		}
	}
	/*
	void OnCollisionStay2D(Collision2D c)
	{
		jump_dir = c.contacts[0].normal;
		can_jump = 2;
		
	}*/
	void OnCollisionEnter2D(Collision2D c)
	{

			
		// walljumppijutut
		if(c.contacts[0].normal.y>=0.0f)
		{
			if(c.gameObject.layer == LayerMask.NameToLayer("Ground"))
			{
				jump_dir = c.contacts[0].normal;
				
				if(jump_dir.y>=0.0f)// wall
					can_jump = 2;
			}
			if(jump_dir.y>=0.9f)// ground
				can_jump = 2;
				
			if(fly_btn)
				can_jump = 0;
		}
	}
}
